home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Loadstar 248
/
248.d81
/
t.ml protocol
< prev
next >
Wrap
Text File
|
2022-08-26
|
7KB
|
404 lines
u
AN ML PROGRAMMER'S GUIDE TO
DOTBASIC PLUS
by Dave Moorman
ML Coders UNITE! You have nothing
to lose but your Chains!
OK, maybe "chains" is too strong a
term. But if you code in 65xx ML, you
know how hard it is to even think in
terms of relocatable code. Our ML
likes absolute addresses. Which is not
a particularly [bad] thing. I mean, we
only have 65536 bytes to worry about!
DotBASIC Plus is designed for
those who have not become addicted
with individual bits and bytes, but
want plenty of power over the machine.
And since DB+ is Adaptable to the
needs of the programmer, we can
provide infinite DB+ commands to do
just that.
But we have to follow a certain
"protocol", a few rules that make DB+
ML code "modulettes" work with each
other and the system. So this article
is about how to write a new DB+
Command.
CHOOSING A NAME
---------------
Obviously, the command name has to
be unique, a legal filename, no more
than 9 characters, and
not include any BASIC 2.0 Keyword!
(You won't believe my own frustration
with command names like .PRINTSTR! The
PRINT is tokenized by BASIC 2.0, and
is not recognized by DotBASIC. Moan!)
The filename for the code must be
DCM.COMMAND.ML
where COMMAND is your Command name.
THE LAYOUT
----------
When a DB+ Command is called from
the DB+ program, the Carry is Cleared.
When the same command is called from
another ML command, the Carry is Set.
This allows us to sort out the two
situations in just four bytes of code:
0000 BCC BAS
0002 BCS ML
Often, the difference between the
two is that the BAS section will
collect parameters from BASIC and put
the values in various places. The ML
portion expects the data to be in such
places.
BAS
**** JSR GETINT
**** STA 900
**** JSR GETINT
**** STA 901
ML
**** LDA 900
**** LDX 901
etc
BUT BACK TO THE HEADER
----------------------
0000 BCC BAS
0002 BCS ML
0004 BYT 255
0005 BYT ",S,Y,N,T,A,X",0
ML
0006 RTS
BAS
0007 ....
Byte 4 of the code is the
beginning of the ML's "include"
section, which ends with a 255 byte.
We will look at this in a moment.
Next comes the "self-documenting"
feature. In the above example, the
text is added to the command name
(when the DB+ programmer types SYS
DD+6) as
COMMAND,S,Y,N,T,A,X
Your code at BAS will need to get
the parameters into the code. We have
some jumps to do this for you:
DD = 14336
GETINT Gets Integer
Returns: LO>.A HI>.X
(.Y not affected)
GETFP Gets Floating Point
Returns Floating Point in ACC#1
GETSTR Gets String
Returns: LEN>.A LO>.X HI>.Y
GETSIN Gets Signed Integer
Returns: LO>.A HI>.X
Allows negative values.
DOING DATA
----------
You can put transitory data
anywhere you think will be safe. I use
the cassette buffer extensively for
put and take situations. Obviously,
this area is no good for values I want
to keep from command call to command
call.
For this, you can set aside
space in your code itself, using the
following method:
DD=14336
SETLOC = DD + 27
TOP
BCC BAS
BCS ML
BYT 255
BYT",x,y",0
ML
RTS
DATA
BYT 0,0,0,0
BAS
LDA#DATA-TOP
LDX#164
JSR SETLOC
JSR GETSIN
LDY#0
CLC
ADC(164),Y
STA(164),Y
INY
TXA
ADC(164),Y
STA(164),Y
JSR GETSIN
LDY#2
ADC(164),Y
STA(164),Y
INY
TXA
ADC(164),Y
STA(164),Y
Here we set aside four bytes at
DATA. To "find" where these bytes are,
we first put the relative location of
DATA (DATA-TOP) in .A, and a zero page
address in .X. Then we use SETLOC,
which finds the current address of the
code and adds the distance to DATA.
The result is put in 164/165, ready
for Indirect Y addressing!
And that is just what we do with
each GETSIN -- adding the value to
each byte in DATA. Later, we can use
the same data to position a sprite or
the cursor.
But, you are saying, you have
several commands that must access the
same safe data. That certainly won't
work with SETLOC. And you are right!
So we have Data Blocks. These are
small PRG files with enough space for
the needed shared data. A Data Block
filename uses a "#" to signify it is
data and not a command. So use your
assembler to create the Data Block
file, with a name such as:
DCM#MYDATA.ML
In your code, you will need to
include the Data Block.
DD = 14336
SETDAT = DD + 30
BCC BAS
BCS ML
BYT 1,"#MYDATA",0,255
BYT ",Q",0
ML
RTS
BAS
LDA#1 ; Index > .A
LDX#164; ZP > .X
JSR SETDAT
The Data Block name (#MYPROG) is
preceded by a number byte which serves
as an index. The name is followed by a
0 byte and the "include" area is
terminated with a 255 byte.
To set the Data Block, the index
number is put in .A and the zero page
address is put in .X. JSR SETDAT then
put the address of the Data Block in
the two zero page bytes, ready for an
Indirect Y call.
SUBROUTINES?
------------
If you absolutely need a
subroutine in your code, you can use
the SETLOC to put the subroutines
address in two zero page bytes. Then
poke a 76 in the byte before the zp
address bytes. Simply JSR to that zp
location.
TOP
BCC BAS
BCS ML
BYT255
BYT0
ML
RTS
ROUTINE
LDA#0
SEC
LOOP
ROL
DEX
BPL LOOP
RTS
BAS
LDA#ROUTINE-TOP
LDX#165
JSR SETLOC
LDA#76
STA164
JSR GETINT
AND#7
TAX
JSR 164
This code uses a subroutine to set
a given bit (bit number in .X). At
BAS, we put the relative address of
ROUTINE in .A and 165 in .X. The
location of ROUTINE is put in 165/166
by SETLOC. Then we put 76 in 164 (JMP
instruction), and we are ready to
roll!
COMMAND CALLING COMMAND
-----------------------
But now for the niftiest trick of
DB+ ML protocol. One command can call
the ML portion of another command!
Let's first write DCM.SETBIT.ML
BCC BAS
BCS ML
BYT255
BYT":ML BIT>900",0
BAS
RTS
ML
LDA#0
SEC
LDX 900
LOOP
ROL
DEX
BPL LOOP
RTS
Simple enough. Now we will write
DCM.SPR1.BC, which will turn on a
given sprite.
DD = 14336
SETML = DD + 21
DOML = DD + 24
BCC BAS
BCS ML
BYT 1,"SETBIT",0,255
BYT ",BIT#",0
ML
RTS
BAS
LDA#1
JSR SETML
JSR GETINT
STA 900
JSR DOML
ORA 53269
STA 53269
RTS
Note that in the include section,
SETBIT does NOT have the preceding
dot. I did this just to confuse
myself! Again, the index number is put
in .A then SETML is called. This sets
up the jump to the code of SETBIT.
Then any data can be set up for the
routine (putting the bit number in
900) and the routine called with DOML.
SUMMARY
-------
That's all there is to it. Do not
jump directly to any location in your
code. Do not load or store a register
directly from or to any location in
the body of your code. But you do have
everything you need to put relative
locations in zero page or find and use
other command codes. Here is a
schematic of the first bytes of your
code:
BCC BAS
BCS ML
BYT<index byte>
BYT<"com-name" or "#data-name">
BYT<0>
BYT<another index byte>
BYT<"com-name" or "#data-name">
BYT<0>
BYT 255 ; end include section
BYT<"syntax info">
BYT 0
Open space
BAS
...
RTS
ML
...
RTS
I am looking forward to any an all
DB+ Commands you might think of. I
believe anything we can do in ML can
become available to DB+ users!
DMM